lexer grammar TemplatingLexer;

options {
	language=CSharp;
}

@lexer::namespace {
	Templating.Grammar.Antlr
}

TOKEN_OP_RBRACE 
    :   '}'
    ;

TOKEN_OP_LBRACKET
    :   '{'
    ;
    
TOKEN_MARK
    :   MARK
    ;

TOKEN_MARK_FOREACH
    :   MARK  FOREACH   ->  mode(ISLAND)
    ;

TOKEN_EXPR
	:	TOKEN_MARK TOKEN_EXPR_NEST
	;

TOKEN_PARTIAL
    :   MARK PARTIAL TOKEN_EXPR_NEST
    ;

TOKEN_EXPR_NEST
	:	TOKEN_OP_LPARENT (TOKEN_EXPR_NEST | TOKEN_CONST_STRING | ~[()])*? TOKEN_OP_RPARENT
	;

TOKEN_OTHER
	:	~[{@}]+
	;

mode ISLAND;

TOKEN_OP_LBRACE		:   '{'     ->      mode(DEFAULT_MODE);
TOKEN_OP_LPARENT    :   '('     ;
TOKEN_OP_RPARENT	:   ')'     ;
TOKEN_OP_EQUAL		:   '='     ;
TOKEN_OP_COMMA      :   ','     ;

TOKEN_BLANK
    :   (NEWLINE | WS)+     ->      skip
    ;

/////////////////////////////////////////////////////////////
// const

TOKEN_CONST_STRING
    :   '"' ( ESC | ~('~' | '"' | [\r\n]))* '"'
    |   '\'' ( ESC | ~('~' | '\'' | [\r\n]))* '\''
    ;

TOKEN_CONST_INTEGER
    :   DIGIT+
    ;

/////////////////////////////////////////////////////////////
// foreach

TOKEN_GROUPBY
    :   G R O U P B Y
    ;

TOKEN_ORDERBY
    :   O R D E R B Y
    ;

TOKEN_INTO
    :   I N T O
    ;

TOKEN_IDENTIFIER
    :	(LETTER | UNDERSCORE) (LETTER | UNDERSCORE | DIGIT)*
    ;

/////////////////////////////////////////////////////////////

fragment
MARK
    :   '@'
    ;

fragment
FOREACH
    :   F O R E A C H
    ;

fragment
PARTIAL
    :   P A R T I A L
    ;

fragment
WS
    :   (' ' | '\t' | '\f')
    ;

fragment
NEWLINE
    :   ('\r')? '\n'
    ;

fragment
DIGIT        
    :    '0'..'9'
    ;

fragment
LETTER
    :    ANSI_L | UNICODE_L
    ;

fragment
ANSI_L
    :    ('a'..'z' | 'A'..'Z')
    ;
    
fragment
ESC
	:	('~' | '\\') ~[\r\n]
	;

fragment
UNICODE_L
    :    '\u0041'..'\u005a'
    |    '\u0061'..'\u007a'
    |    '\u00c0'..'\u00d6'
    |    '\u00d8'..'\u00f6'
    |    '\u00f8'..'\u00ff'
    |    '\u0100'..'\u1fff'
    |    '\u2000'..'\u303f'        
    |    '\u3040'..'\u318f'
    |    '\u3300'..'\u337f'
    |    '\u3400'..'\u3d2d'
    |    '\u4e00'..'\u9fff'
    |    '\uac00'..'\ud7af'
    |    '\uf900'..'\ufaff'
    |    '\uff10'..'\uff19'
    |    '\uff21'..'\uff3a'
    |    '\uff41'..'\uff5a'
    |    '\uff66'..'\uff9d'
    ;

fragment
UNDERSCORE
    :    '_'
    ;

fragment A
    :    ('a' | 'A')
    ;

fragment B
    :    ('b' | 'B')
    ;

fragment C
    :    ('c' | 'C')
    ;

fragment D
    :    ('d' | 'D')
    ;

fragment E
    :    ('e' | 'E')
    ;

fragment F
    :    ('f' | 'F')
    ;

fragment G
    :    ('g' | 'G')
    ;

fragment H
    :    ('h' | 'H')
    ;

fragment I
    :    ('i' | 'I')
    ;

fragment J
    :    ('j' | 'J')
    ;

fragment K
    :    ('k' | 'K')
    ;

fragment L
    :    ('l' | 'L')
    ;

fragment M
    :    ('m' | 'M')
    ;

fragment N
    :    ('n' | 'N')
    ;

fragment O
    :    ('o' | 'O')
    ;

fragment P
    :    ('p' | 'P')
    ;

fragment Q
    :    ('q' | 'Q')
    ;

fragment R
    :    ('r' | 'R')
    ;

fragment S
    :    ('s' | 'S')
    ;

fragment T
    :    ('t' | 'T')
    ;

fragment U
    :    ('u' | 'U')
    ;

fragment V
    :    ('v' | 'V')
    ;

fragment W
    :    ('w' | 'W')
    ;

fragment X
    :    ('x' | 'X')
    ;

fragment Y
    :    ('y' | 'Y')
    ;

fragment Z
    :    ('z' | 'Z')
    ;
